package com.ym.medical.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.GlobalThreadPool;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ym.base.enums.FlagEnum;
import com.ym.common.constant.Constants;
import com.ym.common.constant.DictEnum;
import com.ym.common.enums.SmsTemplateEnum;
import com.ym.common.enums.UserUserTypeEnum;
import com.ym.common.utils.CalcUtil;
import com.ym.common.utils.SmsUtil;
import com.ym.common.utils.StringUtil;
import com.ym.core.annotation.Locker;
import com.ym.core.exception.BusinessException;
import com.ym.core.rabbit.IMessageSenderSV;
import com.ym.core.redis.RedisKeyEnum;
import com.ym.core.utils.tkmybatis.BaseSVImpl;
import com.ym.core.utils.tkmybatis.TK;
import com.ym.medical.dao.CounsellingRoomDao;
import com.ym.medical.dao.DoctorDetailsDao;
import com.ym.medical.dao.DoctorPhoneSettingDao;
import com.ym.medical.dao.InquiryAnnexDao;
import com.ym.medical.dao.InquiryOrderDao;
import com.ym.medical.dao.YunxinUserDao;
import com.ym.medical.domain.bo.pay.WxOrderQueryRespData;
import com.ym.medical.domain.entity.*;
import com.ym.medical.domain.param.CancelOrderParam;
import com.ym.medical.domain.param.ConsultingOrderParam;
import com.ym.medical.domain.param.CounsellingRoomParam;
import com.ym.medical.domain.param.DoctorDetailsParam;
import com.ym.medical.domain.param.DoctorSearchParam;
import com.ym.medical.domain.param.InquiryOrderParam;
import com.ym.medical.domain.param.OrderAndFileParam;
import com.ym.medical.domain.param.OrderParam;
import com.ym.medical.domain.param.TdRecordExampleParam;
import com.ym.medical.domain.vo.*;
import com.ym.medical.enums.*;
import com.ym.medical.service.*;
import com.ym.medical.service.task.AutoCompleteOrderTask;
import com.ym.medical.service.task.ReleasePoolOrderTask;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 问诊订单Service业务层处理
 *
 * @author ym
 * @date 2020-08-24
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class InquiryOrderSVImpl extends BaseSVImpl<InquiryOrderEntity, InquiryOrderDao> implements IInquiryOrderSV {

	@Autowired
	private IOrderPoolSV orderPoolSV;
	@Autowired
	private IOrderFlowRecordSV orderFlowRecordSV;
	@Autowired
	private IStudioPersonnelSV studioPersonnelSV;
	@Autowired
	private ICounsellingRoomSV counsellingRoomSV;
	@Autowired
	private IMessageSenderSV messageSenderSV;
	@Autowired
	private ICommonSV commonSV;

	@Autowired
	private YunxinUserDao yunxinUserDao;

	@Autowired
	private CounsellingRoomDao counsellingRoomDao;

	@Autowired
	private DoctorDetailsDao doctorDetailsDao;

	@Autowired
	private IChatroomPersonnelSV chatroomPersonnelSV;

	@Autowired
	private ISysCodeRuleSV generateCodeRuleSV;

	@Autowired
	private InquiryAnnexDao inquiryAnnexDao;

	@Autowired
	private IAddressListSV addressListSV;

	@Autowired
	private IAddressGroupSV addressGroupSV;
	@Autowired
	private IDoctorStudioSV doctorStudioSV;
	@Autowired
	private IConsumeDetailsSV consumeDetailsSV;
	@Autowired
	private IAccountSV accountSV;

	@Autowired
	private DoctorPhoneSettingDao doctorPhoneSettingDao;

	@Autowired
	private ISysDictSV sysDictSV;

	@Autowired
	private IInquiryOrderContentSV inquiryOrderContentSV;

	@Autowired
	private IDoctorDetailsSV doctorDetailsSV;

	@Autowired
	private IJpushAccountSV jpushAccountSV;

	@Autowired
	private IAxbResultSV iAxbResultSV;

	@Autowired
	private IOrderPaySV iOrderPaySV;

	@Autowired
	private IInformationSV informationSV;

	@Autowired
	private IStudioPersonServiceSV studioPersonServiceSV;

	@Autowired
	private ICommentRecordSV iCommentRecordSV;

	@Autowired
	private IInquiryAnnexSV inquiryAnnexSV;

	@Autowired
	private ITextRuleSV textRuleSV;

	@Autowired
	private IUserSV userSV;

	@Autowired
	private IUserTaglibrarySV userTaglibrarySV;

	@Autowired
	private IMindSV mindSV;

	@Autowired
	private IDoctorServiceItemSV doctorServiceItemSV;

	@Autowired
	private ICouponReceiveRecordSV receiveRecordSV;

	@Autowired
	private ICouponReceiveRecordSV couponReceiveRecordSV;

	@Autowired
	private IOrderPaySV orderPaySV;

	@Autowired
	private IDoctorServicePriceSV doctorServicePriceSV;

	@Autowired
	private ISysConfigSV configSV;

	/**
	 * 订单取消
	 */
	@Override
	public int cancelOrder(CancelOrderParam cancelOrderParam) {
		if (null == cancelOrderParam.getPrDuration()) {
			throw new BusinessException("参数不完整");
		}

		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String time = dateFormat.format(new Date());
		String appointTime1 = dateFormat.format(cancelOrderParam.getAppointTime());
		long ioId = cancelOrderParam.getIoId();
		if (time.equals(appointTime1)) {
			//查询订单状态?
			long time1 =
					cancelOrderParam.getAppointTime().getTime();
			long time2 = System.currentTimeMillis();
			long diff = TimeUnit.MILLISECONDS.toMinutes(time1 - time2);
			log.info("取消订单时差" + diff);
			if (diff > 0 && diff <= 30) {
				throw new BusinessException("离近半小时内不能取消喔");
			}
		}

		//发起退费
		OrderParam orderModel = new OrderParam();
		orderModel.setOutTradeNo(cancelOrderParam.getIoNum());
		orderModel.setProductId(String.valueOf(ioId));
		JSONObject result = iOrderPaySV.refundOrder(orderModel);
		if ("SUCCESS".equals(result.get("returnCode")) && "SUCCESS".equals(result.get("resultCode"))) {
			return 1;
		} else {
			throw new RuntimeException();
		}
	}

	@Override
	public void saveOrder(InquiryOrderParam inquiryOrder) {
		//全科默认30次规则
		TextRuleEntity textRule = textRuleSV.selectDefaultTextRule();
		List<DoctorServicePriceEntity> doctorServicePrices = null;
		if (textRule != null) {
			doctorServicePrices = doctorServicePriceSV.selectList(DoctorServicePriceEntity.builder().ruleId(textRule.getId()).build());
		}
		Long ruleId = null;
		if (!doctorServicePrices.isEmpty()) {
			ruleId = doctorServicePrices.get(0).getId();
		}
		inquiryOrder.setRuleId(ruleId);
		InquiryOrderEntity covert = inquiryOrder.covert();
		generateOrder(covert);
		this.insert(covert);
		/*保存附件*/
		//问诊附件表信息
		InquiryAnnexEntity inquiryAnnex = new InquiryAnnexEntity();
		inquiryAnnex.setIoId(covert.getId());
		inquiryAnnex.setIoNum(inquiryOrder.getIoNum());
		inquiryAnnex.setFileInforId(inquiryOrder.getFileInforId());
		inquiryAnnexDao.insertSelective(inquiryAnnex);

		orderPoolSV.put(RedisKeyEnum.GENERAL_DOCTOR_POOL, String.valueOf(covert.getId()));
		jpushAccountSV.pushOrderMsg2Doctors(covert.getId());
	}

	/**
	 * 完善保存订单信息
	 *
	 * @param inquiryOrder
	 */
	private void generateOrder(InquiryOrderEntity inquiryOrder) {
		/* 生成订单号*/
		inquiryOrder.setIoNum(generateCodeRuleSV.createCode(CodeRuleEnum.VISIT_ORDER));
		/*设置订单状态为待接单*/
		inquiryOrder.setIoState(InquiryOrderStateEnum.WAITING_LIST.getKey());
		/*设置订单支付状态为全科订单*/
		inquiryOrder.setPaymentState(InquiryOrderPaymentStateEnum.FREE.getKey());
		/*设置订单类型为图文问诊*/
		inquiryOrder.setIoType(InquiryOrderIoTypeEnum.BY_CONSULTING.getKey());
	}

	@Override
	public int updateById(InquiryOrderEntity inquiryOrder) {
		return this.updateById(inquiryOrder);
	}

	@Override
	public InquiryOrderEntity findById(long inquiryOrderId) {
		return this.selectById(inquiryOrderId);
	}

	@Override
	public InquiryOrderEntity findByModel(InquiryOrderParam inquiryOrderModel) {
		List<InquiryOrderEntity> inquiryOrders = list(inquiryOrderModel);
		return inquiryOrders.isEmpty() ? null : inquiryOrders.get(0);
	}

	@Override
	public List<InquiryOrderEntity> list(InquiryOrderParam inquiryOrderModel) {
		return this.selectList(inquiryOrderModel.covert());
	}

	@Override
	public List<OrdersVo> getOrders(RedisKeyEnum generalDoctorPool, UserEntity currentUser) {
		// 0.当前人的接诊状态，关闭直接返回空
		DoctorDetailsEntity docotrDetails = doctorDetailsSV.findById(currentUser.getId());
		// todo 暂停接单返回空
		//if (docotrDetails.getAccept().equals(FlagEnum.NO.getKey())) {
		//	return Collections.emptyList();
		//}
		// 1.当前人可刷单数量
		int random = calculateTheQuantityTaken(currentUser);
		ArrayList<String> orders = null;
		// 2.查询医生可刷单的工作室，专科多个工作室刷单，全科一个工作室
		StudioPersonnelEntity studioPersonnel = StudioPersonnelEntity.builder()
				.doctId(currentUser.getId())
				.deleted(FlagEnum.NO.getKey())
				.admsStateDoctor(FlagEnum.IS.getKey())
				.admsStateStudio(FlagEnum.IS.getKey())
				.build();
		List<Long> workIds = studioPersonnelSV.getSpecialistToGrabList(studioPersonnel);
		if (workIds.isEmpty()) {
			// 没有可刷单的工作室返回空
			return Collections.emptyList();
		}
		if (generalDoctorPool == RedisKeyEnum.GENERAL_DOCTOR_POOL) {
			// 全科医生
			orders = orderPoolSV.pullOrdersRandom(generalDoctorPool, random);
		} else {
			//专科医生
			orders = new ArrayList<>();
			for (Long id : workIds) {
				ArrayList<String> strings = orderPoolSV.pullOrdersRandom(generalDoctorPool, random, "WORK", id.toString());
				orders.addAll(strings);
			}
			// 打乱顺序
			Collections.shuffle(orders);
			int dif = orders.size() - random;
			if (dif > 0) {
				ArrayList<String> newOrders = new ArrayList<>();
				for (int i = 0; i < random; i++) {
					newOrders.add(orders.get(i));
				}
				orders = newOrders;
			}

		}
		if (orders == null || orders.isEmpty()) {
			return Collections.emptyList();
		}
		// 真实的订单号，获取订单信息
		List<Long> collect = orders.stream().map(n -> {
			return Long.valueOf(n.substring(n.lastIndexOf(":") + 1, n.length()));
		}).collect(Collectors.toList());
		// 查询订单信息
		List<OrdersVo> list = mapper.getOrdersInPool(collect);
		return list;
	}


	/**
	 * 根据当前用户计算他一次取出的数量
	 *
	 * @param currentUser
	 * @return
	 */
	private int calculateTheQuantityTaken(UserEntity currentUser) {

		return 5;
	}

	@Override
	public List<JSONObject> initSpecialistPool() {
		String sql = " SELECT " +
				"      a.id,b.doctor_ds_id workId " +
				"    FROM  inquiry_order a " +
				"    left join order_flow_record_view b on a.id = b.order_id " +
				"    where b.doctor_ds_id is not null and  b.type = #{params.type} and (b.status = #{params.status1} or b.status = #{params.status2} ) and a.io_state = #{params.ioState} and a.io_type = #{params.ioType}";
		Map<String, Object> params = new HashMap<>();
		params.put("status1", OrderFlowRecordSatusEnum.NOT_ROB_SINGLE.getKey());
		params.put("status2", OrderFlowRecordSatusEnum.HAVE_BEEN_ABANDONED.getKey());
		params.put("ioState", InquiryOrderStateEnum.WAITING_LIST.getKey());
		params.put("ioType", InquiryOrderIoTypeEnum.BY_CONSULTING.getKey());
		params.put("type", CounsellingRoomCourTypeEnum.SPECIALIZED_SUBJECT.getKey());
		return commonSV.queryListJson(sql, params);
	}

	@Override
	public List<JSONObject> initGeneralPool() {
		String sql = " SELECT " +
				"      a.id " +
				"    FROM  inquiry_order a " +
				"    left join order_flow_record_view b on a.id = b.order_id " +
				"    where (  b.id is null or (b.type = #{params.type} and b.status = #{params.status}) ) and a.io_state = #{params.ioState} and a.io_type = #{params.ioType}";
		Map<String, Object> params = new HashMap<>();
		params.put("status", OrderFlowRecordSatusEnum.HAVE_BEEN_ABANDONED.getKey());
		params.put("ioState", InquiryOrderStateEnum.WAITING_LIST.getKey());
		params.put("ioType", InquiryOrderIoTypeEnum.BY_CONSULTING.getKey());
		params.put("type", CounsellingRoomCourTypeEnum.GENERAL.getKey());
		return commonSV.queryListJson(sql, params);
	}

	@Override
	@Locker(key = RedisKeyEnum.POOL_ORDER_LOCK, paramExp = "['$']", noGetMsg = "订单已被抢")
	public void grabOrder(String orderId, RedisKeyEnum poolType, UserEntity currentUser) {
		Long workId = orderExist(poolType, orderId);
		if (poolType == RedisKeyEnum.GENERAL_DOCTOR_POOL) {
			//全科医生抢单
			generalDockerGrabOrder(poolType, orderId, currentUser);
		} else if (poolType == RedisKeyEnum.SPECIALIST_DOCTOR_POOL) {
			//专科医生抢单
			specialistDockerGrabOrder(poolType, orderId, currentUser, "WORK", workId.toString());
		}
	}


	/**
	 * 抢单后未回复,释放订单逻辑。点了答复就会创建聊天室。
	 *
	 * @param poolType 抢单池类型
	 * @param orderId  订单ID
	 * @param userId   用户ID
	 * @param extra    额外Key
	 */
	@Override
	public void releasePoolOrder(RedisKeyEnum poolType, String orderId, Long userId, String... extra) {
		OrderFlowRecordEntity newByOrderId = orderFlowRecordSV.findNewByOrderId(Long.valueOf(orderId));
		CounsellingRoomEntity byModel = counsellingRoomSV.findByModel(CounsellingRoomEntity.builder().ioId(Long.valueOf(orderId)).orderFlowRecordId(newByOrderId.getId()).build());
		if (byModel != null) {
			return;
		}
		InquiryOrderEntity inquiryOrder = new InquiryOrderEntity();
		//抢单后,不回复.
		OrderFlowRecordEntity orderFlowRecordUpdate = new OrderFlowRecordEntity();
		orderFlowRecordUpdate.setId(newByOrderId.getId());
		orderFlowRecordUpdate.setStatus(OrderFlowRecordSatusEnum.HAVE_BEEN_ABANDONED.getKey());
		// 流转作废
		orderFlowRecordSV.updateById(orderFlowRecordUpdate);
		// 订单状态还原
		inquiryOrder.setId(Long.valueOf(orderId));
		inquiryOrder.setIoState(InquiryOrderStateEnum.WAITING_LIST.getKey());
		this.updateById(inquiryOrder);
		orderPoolSV.put(poolType, orderId, extra);
		log.info("用户[{}]抢单[{}]后未回复,订单恢复抢单池中", userId, orderId);
	}

	/**
	 * 全科医生抢单
	 *
	 * @param orderId
	 * @param user
	 */
	private void generalDockerGrabOrder(RedisKeyEnum poolType, String orderId, UserEntity user) {
		Long orderIdL = Long.valueOf(orderId);
		// 1.将订单更改为已接单
		InquiryOrderEntity inquiryOrder = new InquiryOrderEntity();
		inquiryOrder.setId(orderIdL);
		inquiryOrder.setIoState(InquiryOrderStateEnum.HAVE_ORDER.getKey());
		this.updateById(inquiryOrder);
		// 2.插入订单流转记录表
		OrderFlowRecordEntity orderFlowRecord = new OrderFlowRecordEntity();
		// 查询该医生工作室信息
		StudioPersonnelEntity studioPersonId = getDoctorStudioPersonId(user.getId());
		orderFlowRecord.setOrderId(orderIdL);
		orderFlowRecord.setDoctorDsId(studioPersonId.getDsId());
		orderFlowRecord.setDoctorId(user.getId());
		orderFlowRecord.setType(OrderFlowRecordTypeEnum.GENERAL.getKey());
		orderFlowRecord.setStatus(OrderFlowRecordSatusEnum.HAS_SEIZED_THE_SINGLE.getKey());
		orderFlowRecord.setDoctorOrderTime(new Date());
		orderFlowRecord.setDsOrderTime(new Date());
		orderFlowRecordSV.save(orderFlowRecord);
		// 4.创建超时未答复放入订单池任务
		JSONObject params = new JSONObject();
		params.put("poolType", poolType);
		params.put("orderId", orderId);
		params.put("doctorId", user.getId());
		ReleasePoolOrderTask releasePoolOrderTask = new ReleasePoolOrderTask("抢单超时释放订单", TimeUnit.MINUTES.toMillis(orderExpirationTime()), params);
		messageSenderSV.sendDelayTask(releasePoolOrderTask);
		// end,从抢单池移除该订单
		orderPoolSV.remove(poolType, orderId);
	}

	/**
	 * 专科医生抢单
	 *
	 * @param orderId
	 * @param user
	 */
	private void specialistDockerGrabOrder(RedisKeyEnum poolType, String orderId, UserEntity user, String... extra) {
		Long orderIdL = Long.valueOf(orderId);
		// 1.将订单更改为已接单
		InquiryOrderEntity inquiryOrder = new InquiryOrderEntity();
		inquiryOrder.setId(orderIdL);
		inquiryOrder.setIoState(InquiryOrderStateEnum.HAVE_ORDER.getKey());
		this.updateById(inquiryOrder);
		// 2.新增流转记录,回填抢单人信息
		OrderFlowRecordEntity newByOrderId = orderFlowRecordSV.findNewByOrderId(orderIdL);
		OrderFlowRecordEntity orderFlowRecord = new OrderFlowRecordEntity();
		BeanUtils.copyProperties(newByOrderId, orderFlowRecord);
		orderFlowRecord.setDoctorId(user.getId());
		orderFlowRecord.setStatus(OrderFlowRecordSatusEnum.HAS_SEIZED_THE_SINGLE.getKey());
		orderFlowRecord.setDoctorOrderTime(new Date());
		orderFlowRecordSV.save(orderFlowRecord);
		// 4.创建超时未答复放入订单池任务
		JSONObject params = new JSONObject();
		params.put("poolType", poolType);
		params.put("orderId", orderId);
		params.put("doctorId", user.getId());
		ReleasePoolOrderTask releasePoolOrderTask = new ReleasePoolOrderTask("抢单超时释放订单", TimeUnit.MINUTES.toMillis(orderExpirationTime()), params);
		messageSenderSV.sendDelayTask(releasePoolOrderTask);
		// end,从抢单池移除该订单
		orderPoolSV.remove(poolType, orderId, extra);
	}

	@Override
	public List<JSONObject> getGeneralGrabUnReplay() {
		Map<String, Object> params = new HashMap<>();
		params.put("state", InquiryOrderStateEnum.HAVE_ORDER.getKey());
		params.put("type", OrderFlowRecordTypeEnum.GENERAL.getKey());
		params.put("ioType", InquiryOrderIoTypeEnum.BY_CONSULTING.getKey());
		String sql = " select  " +
				" a.id orderId, " +
				" b.id,  " +
				" b.doctor_order_time orderTime, " +
				" b.doctor_id doctorId, " +
				" b.type, " +
				" c.id roomId " +
				" from inquiry_order a " +
				" left join order_flow_record_view b on a.id = b.order_id " +
				" left join counselling_room c on b.id = c.order_flow_record_id  " +
				" where  a.io_state = #{params.state} and c.id is null and b.type = #{params.type} and a.io_type = #{params.ioType}";
		return commonSV.queryListJson(sql, params);
	}

	@Override
	public List<JSONObject> getSpecialistGrabUnReplay() {
		Map<String, Object> params = new HashMap<>();
		params.put("state", InquiryOrderStateEnum.HAVE_ORDER.getKey());
		params.put("type", OrderFlowRecordTypeEnum.SPECIALIZED_SUBJECT.getKey());
		params.put("ioType", InquiryOrderIoTypeEnum.BY_CONSULTING.getKey());
		String sql = " select  " +
				" a.id orderId, " +
				" b.id,  " +
				" b.doctor_order_time orderTime, " +
				" b.doctor_id doctorId, " +
				" c.id roomId, " +
				" b.type, " +
				" b.doctor_ds_id workId " +
				" from inquiry_order a " +
				" left join order_flow_record_view b on a.id = b.order_id " +
				" left join counselling_room c on b.id = c.order_flow_record_id  " +
				" where b.doctor_ds_id is not null and a.io_type=#{params.ioType} and  a.io_state = #{params.state} and c.id is null and b.type = #{params.type}";
		return commonSV.queryListJson(sql, params);
	}

	/**
	 * 修改咨询状态
	 *
	 * @param counsellingRoom
	 * @return
	 */
	@Override
	public boolean updateStatus(CounsellingRoomEntity counsellingRoom) {
		counsellingRoomDao.updateByPrimaryKeySelective(counsellingRoom);
		return false;
	}


	/**
	 * 1. 医生抢单后计算医生的分成金额
	 * 1.1 查询分成信息
	 * 1.2 查询订单信息
	 * 1.3 从工作室中解冻该订单的价格（从解冻价格中减去）更新工作室
	 * 1.4 根据分成比例计算每个医生的分成金额
	 * <p>
	 * 2. 更新医生的分成金额 消费明细
	 * 2.1 分别更新每个医生的余额
	 * 2.2 添加每个医生的消费明细
	 * 3. 构建一条咨询聊天室记录 （有创建 没有直接返回聊天室id）
	 * 4. 添加双方到聊天室人员
	 * 5. 建立医患通讯录关系
	 * 6. 创建24小时订单完成任务
	 *
	 * @param orderId
	 * @param currentDocId
	 * @param doctorType
	 * @return
	 */

	@Override
	@Locker(key = RedisKeyEnum.REPLY_REFUND_KEY, paramExp = "['$']", noGetMsg = "该订单申请退款中！不能答复")
	public Long answerOrder(Long orderId, Long currentDocId, CounsellingRoomCourTypeEnum doctorType) {
		// 1.验证是否可以答复
		OrderFlowRecordEntity orderFlowRecord = verifyCanReply(orderId, currentDocId);
		// 当前订单信息
		InquiryOrderEntity inquiryOrder = this.findById(orderId);
		// 2.点击答复后创立聊天室
		Long roomId = createRoomWhenAnswer(inquiryOrder, orderFlowRecord, currentDocId);
		// 4.执行和答复聊天室无关的业务操作
		asyncAnswerAfter(inquiryOrder, orderFlowRecord, currentDocId, roomId, doctorType);
		// 5.必须最后一步，创建24小时订单完成任务
		JSONObject params = new JSONObject();
		params.put("orderId", orderId);
		params.put("roomId", roomId);
		AutoCompleteOrderTask releasePoolOrderTask = new AutoCompleteOrderTask("超时自动完成订单", TimeUnit.HOURS.toMillis(orderCompletionTime()), params);
		messageSenderSV.sendDelayTask(releasePoolOrderTask);
		// 6.检测发送模板扩展消息
		inquiryOrderContentSV.sendExpandMsg2Doctor(inquiryOrder, roomId, currentDocId);
		return roomId;

	}


	/**
	 * 查询订单问诊详情
	 *
	 * @param orderId
	 * @return
	 */
	@Override
	public CounsellingRoomRecordVO selectOrderDesc(Long orderId) {
		List<CounsellingRoomRecordVO> counsellingRoomRecordVOS = counsellingRoomSV.listPatientVisitRecord(
				CounsellingRoomParam.builder().id(orderId).build()
		);
		if (counsellingRoomRecordVOS == null || counsellingRoomRecordVOS.isEmpty()) {
			throw new BusinessException("没有查到该订单");
		}
		return counsellingRoomRecordVOS.get(0);
	}

	/**
	 * 更新医生分成信息
	 *
	 * @param orderId
	 */
	@Override
	public void updateDocDivide(Long orderId) {
		//1. 判断订单是否可分成
		OrderFlowRecordEntity orderFlowRecord = orderFlowRecordSV.findNewByOrderId(orderId);
		if (orderFlowRecord == null) {
			throw new BusinessException("订单流转记录为空");
		}
		Long doctorId = orderFlowRecord.getDoctorId();
		if (doctorId == null) {
			throw new BusinessException("该订单异常{没有抢单人}");
		}
		String doctorType = doctorDetailsDao.selectByPrimaryKey(doctorId).getDoctCategory();
		if (CounsellingRoomCourTypeEnum.GENERAL.getKey().equals(doctorType)) {
			return;   // 全科 直接return
		}
		Long doctorDsId = orderFlowRecord.getDoctorDsId();
		InquiryOrderEntity inquiryOrder = this.findById(orderId);

		// todo 这里取的ioTypeName
		String ioTypeName = inquiryOrder.getIoType();
		Long userId = inquiryOrder.getUserId();
		BigDecimal paymentPrice = inquiryOrder.getPaymentPrice();
		BigDecimal otherAmt = BigDecimal.valueOf(0);

		//双方账户
		AccountEntity userAccount = accountSV.selectAccountByUserId(userId);
		AccountEntity doctorAccount = accountSV.selectAccountByUserId(doctorId);
		//2. 余额支付时 更新患者冻结余额
		if (PaymentWayEnum.ACCOUNT.getKey().equals(inquiryOrder.getPaymentWay())) {
			if (userAccount.getFreezeBalance().compareTo(paymentPrice) == -1) {
				log.info("该患者账单冻结金额不足 订单号: {}", inquiryOrder.getIoNum());
				return;
			}
			userAccount.setFreezeBalance(userAccount.getFreezeBalance().subtract(paymentPrice));
			accountSV.updateById(userAccount);
		}

		//3. 判断优惠劵发放方式 (如果是平台发放的 金额为总金额)
		Long couponRecordId = inquiryOrder.getRelId();
		if (couponRecordId != null) {
			CouponReceiveRecordEntity couponReceiveRecord = couponReceiveRecordSV.selectById(couponRecordId);
			if (CouponSendWayEnum.EXCHANGE.getKey().equals(couponReceiveRecord.getSendWay())) {
				paymentPrice = inquiryOrder.getPayableAmount();
			}
		}

		//4. 更新患者交易明细中的对方账户主键
		List<ConsumeDetailsEntity> consumeDetailsList = consumeDetailsSV.selectList(ConsumeDetailsEntity.builder().cashFlow(CashFlowEnum.EXPEND.getKey()).accId(userAccount.getId()).tradeNo(inquiryOrder.getIoNum()).build());
		if (consumeDetailsList.isEmpty()) {
			log.error("没有获取到该患者的消费明细");
			return;
		}
		log.info("获取患者的消费明细", consumeDetailsList);
		ConsumeDetailsEntity consumeDetails = consumeDetailsList.get(0);
		consumeDetails.setDfAccId(doctorAccount.getId());
		consumeDetailsSV.updateById(consumeDetails);

		//5. 更新医生的账户 交易明细
		String tdBody = null;
		if (doctorDsId == null) {
			log.info("抢单人没有开通工作室! 医生id:{}", doctorId);
			//更新抢单医生的金额
			doctorAccount.setAccBalance(doctorAccount.getAccBalance().add(paymentPrice));
			accountSV.updateAccountById(doctorAccount);
			//2.2更新抢单医生(个人)的消费明细
			tdBody = ioTypeName + "费-收入";
			updateDoctorDetail(inquiryOrder, consumeDetails, tdBody, paymentPrice, null, doctorAccount);
		} else {
			//获取工作室宿主id
			Long hostId = null;
			DoctorStudioEntity doctorStudioEntity = new DoctorStudioEntity();
			doctorStudioEntity.setId(doctorDsId);
			List<DoctorStudioEntity> doctorStudios = doctorStudioSV.selectList(doctorStudioEntity);
			if (!doctorStudios.isEmpty()) {
				hostId = doctorStudios.get(0).getBelongPerson();
			}
			log.info("该医生的工作室宿主id: {}", hostId);
			if (doctorId.equals(hostId)) {
				//如果是宿主抢单 直接给医生增加余额 和消费明细
				//1.更新宿主的余额
				doctorAccount.setAccBalance(doctorAccount.getAccBalance().add(paymentPrice));
				accountSV.updateById(doctorAccount);
				//2.2更新宿主医生的消费明细
				tdBody = ioTypeName + "费-收入";
				updateDoctorDetail(inquiryOrder, consumeDetails, tdBody, paymentPrice, doctorDsId, doctorAccount);
			} else {
				log.info("抢单人是工作室下属人员，计算分成比例");
				//查询工作室宿主用户的账户
				AccountEntity hostAccount = accountSV.selectAccountByUserId(hostId);

				//获取工作室人员信息
				StudioPersonnelEntity flowerPersonnel = studioPersonnelSV.selectOne(StudioPersonnelEntity.builder().dsId(doctorDsId).doctId(doctorId).build());
				//查询工作室下属的分成比例
				List<StudioPersonServiceEntity> studioPersonServices = studioPersonServiceSV.selectList(StudioPersonServiceEntity.builder().build().builder().studioPersonId(flowerPersonnel.getId()).serviceId(inquiryOrder.getIoType()).build());
				if (studioPersonServices.isEmpty() || studioPersonServices.get(0).getProportion() == null) {
					throw new BusinessException("该工作室还没有设置该抢单人的分成信息");
				}
				BigDecimal proportion = studioPersonServices.get(0).getProportion();   //宿主医生的分成比例
				BigDecimal flowerPrice = paymentPrice.multiply(proportion);        //抢单医生分成金额
				BigDecimal hostPrice = paymentPrice.subtract(flowerPrice);        //宿主分成金额
				BigDecimal flowerAdvance = CalcUtil.mul(consumeDetails.getAdvanceAmount(), proportion).decimalValue(2);        //抢单医生平台垫付
				BigDecimal hostAdvance = CalcUtil.sub(consumeDetails.getAdvanceAmount(), flowerAdvance).decimalValue(2);        //宿主平台垫付

				//更新下属账户
				doctorAccount.setAccBalance(doctorAccount.getAccBalance().add(flowerPrice));
				accountSV.updateById(doctorAccount);
				//更新宿主账户
				hostAccount.setAccBalance(hostAccount.getAccBalance().add(hostPrice));
				accountSV.updateById(hostAccount);
				//2.2更新宿主医生的消费明细
				tdBody = "个人工作室分成-收入";
				consumeDetails.setAdvanceAmount(hostAdvance);  //宿主平台垫付
				updateDoctorDetail(inquiryOrder, consumeDetails, tdBody, hostPrice, doctorDsId, hostAccount);

				//2.2更新下属医生的消费明细
				UserEntity user = userSV.selectById(hostId);
				tdBody = user.getRealName() + "工作室分成-收入";
				//如果是下属抢单 没有平台垫付和手续费
				consumeDetails.setOtherAmt(otherAmt);
				consumeDetails.setAdvanceAmount(flowerAdvance);    //抢单医生平台垫付
				updateDoctorDetail(inquiryOrder, consumeDetails, tdBody, flowerPrice, doctorDsId, doctorAccount);
				return;
			}
		}
		log.info("订单结束，结束订单让患者评价消息并发送");
		informationSV.generateInquiryInformation(orderId, Constants.InquiryAdvice.EVALUATE);
	}

	/**
	 * 更新医生的消费明细
	 *
	 * @param inquiryOrder
	 * @param consumeDetails 患者的交易明细
	 * @param doctorDsId
	 * @param doctorAccount
	 */
	private void updateDoctorDetail(InquiryOrderEntity inquiryOrder, ConsumeDetailsEntity consumeDetails, String tdBody, BigDecimal price, Long doctorDsId, AccountEntity doctorAccount) {
		ConsumeDetailsEntity hostConsumeDetails = new ConsumeDetailsEntity();
		hostConsumeDetails.setCashFlow(CashFlowEnum.INCOME.getKey());
		hostConsumeDetails.setTradeNo(inquiryOrder.getIoNum());
		hostConsumeDetails.setStudioId(doctorDsId);
		hostConsumeDetails.setTdNo(consumeDetails.getTdNo());
		if (StrUtil.isEmpty(tdBody)) {
			tdBody = consumeDetails.getTdBody();
		}
		hostConsumeDetails.setTdAmount(price);
		hostConsumeDetails.setTdBody(tdBody);
		hostConsumeDetails.setPayType(consumeDetails.getPayType());
		hostConsumeDetails.setPayAcc(consumeDetails.getPayAcc());
		hostConsumeDetails.setTdTime(consumeDetails.getTdTime());
		hostConsumeDetails.setDfAccId(consumeDetails.getAccId());
		hostConsumeDetails.setAftTdAmount(doctorAccount.getAccBalance());
		hostConsumeDetails.setAccId(doctorAccount.getId());
		hostConsumeDetails.setTdType(consumeDetails.getTdType());
		hostConsumeDetails.setCreateTime(new Date());
		hostConsumeDetails.setAdvanceAmount(consumeDetails.getAdvanceAmount());
		hostConsumeDetails.setOtherAmt(consumeDetails.getOtherAmt());
		consumeDetailsSV.insert(hostConsumeDetails);
	}

	/**
	 * 建立医患关系
	 *
	 * @param patientId 患者ID
	 * @param doctorId  医生ID
	 */
	private void establishDoctorPatientRelationship(Long patientId, Long doctorId) {
		/*查询通讯录关系*/

		AddressGroupEntity addressGroupModel = new AddressGroupEntity();
		addressGroupModel.setAlgIdent(AddressGroupAlgIdentEnum.IN_PATIENTS_WITH.getKey());
		addressGroupModel.setAlgType(AddressGroupAlgTypeEnum.System.getKey());
		//addressGroupModel.setAlgName(SystemGroupEnum.PATIENT.ALL.getName());
		addressGroupModel.setUserId(doctorId);
		//List<AddressGroup> addressGroups = addressGroupSV.selectByModel(addressGroupModel);
		AddressGroupEntity addressGroup = null;
		//if (addressGroups != null && !addressGroups.isEmpty()) {
		//addressGroup = addressGroups.get(0);
		//}
		// 全部患者添加
		//addressListSV.addFriend(patientId, doctorId, "03", addressGroup == null ? null : addressGroup.getId());
		addressGroupModel.setAlgName(SystemGroupEnum.PATIENT.INQUIRY.getName());
		//addressGroup = null;
		List<AddressGroupEntity> addressGroups = addressGroupSV.selectList(addressGroupModel);
		if (addressGroups != null && !addressGroups.isEmpty()) {
			addressGroup = addressGroups.get(0);
		}
		// 问诊患者添加
		addressListSV.addFriend(patientId, doctorId, "03", addressGroup == null ? null : addressGroup.getId());
	}


	/**
	 * 接单后自动完成订单任务
	 *
	 * @param orderId
	 * @param roomId
	 */
	@Override
	public void autoCompleteOrder(Long orderId, Long roomId) {
		log.info("订单结束，修改订单状态");
		// 查看是否已经关闭,关闭则不更新
		InquiryOrderEntity query = new InquiryOrderEntity();
		query.setId(orderId);
		InquiryOrderEntity inquiryOrders = this.selectOne(query);
		String ioState = inquiryOrders.getIoState();
		if (InquiryOrderStateEnum.HAVE_ORDER.getKey().equals(ioState)) {
			// 订单状态更新
			InquiryOrderEntity InquiryOrder = new InquiryOrderEntity();
			InquiryOrder.setId(orderId);
			InquiryOrder.setIoState(InquiryOrderStateEnum.COMPLETE.getKey());
			InquiryOrder.setIoEndtime(new Date());
			this.updateById(InquiryOrder);
			// 相关最新的流转记录更新
			OrderFlowRecordEntity newByOrderId = orderFlowRecordSV.findNewByOrderId(orderId);
			OrderFlowRecordEntity orderFlowRecord = new OrderFlowRecordEntity();
			orderFlowRecord.setId(newByOrderId.getId());
			orderFlowRecord.setStatus(OrderFlowRecordSatusEnum.HAVE_STATEMENTS.getKey());
			orderFlowRecordSV.updateById(orderFlowRecord);
			// 咨询室状态更新
			CounsellingRoomEntity updateCou = new CounsellingRoomEntity();
			updateCou.setId(roomId);
			updateCou.setCourState(CounsellingRoomStateEnum.HAS_ENDED.getKey());
			updateCou.setCourTimeEnd(new Date());
			updateCou.setOrderFlowRecordId(newByOrderId.getId());
			counsellingRoomSV.update(updateCou);

			//更新医生的分成金额及消费明细
			log.info("订单结束，更新医生的分成金额及消费明细");
			updateDocDivide(orderId);
			log.info("订单结束，更新医生的分成金额及消费明细成功");


		}
	}

	public CounsellingRoomEntity geneCounsellingRoom(Long orderId, Long userId, Long orderFlowRecordId, Long doctorId, Long studioPersonId) {
		CounsellingRoomEntity counsellingRoom = new CounsellingRoomEntity();
		counsellingRoom.setIoId(orderId);
		counsellingRoom.setDsId(studioPersonId);
		/*订单流转记录主键*/
		counsellingRoom.setOrderFlowRecordId(orderFlowRecordId);
		/*根据用户id查询云信账号*/
		counsellingRoom.setInquiryAccid(getYunXinUser(userId).getAccid());
		counsellingRoom.setReplyAccid(getYunXinUser(doctorId).getAccid());
		/*咨詢室id*/
		counsellingRoom.setRoomId(IdUtil.fastSimpleUUID());

		/*查询该医生是专科 全科？*/
		DoctorDetailsEntity doctorDetails = doctorDetailsDao.selectByPrimaryKey(doctorId);
		if (doctorDetails.getDoctCategory().equals(CounsellingRoomCourTypeEnum.SPECIALIZED_SUBJECT.getKey())) {
			//专科
			counsellingRoom.setCourType(CounsellingRoomCourTypeEnum.SPECIALIZED_SUBJECT.getKey());
		} else {
			//全科
			counsellingRoom.setCourType(CounsellingRoomCourTypeEnum.GENERAL.getKey());
		}
		//已答复
		counsellingRoom.setCourState(CounsellingRoomStateEnum.HAVE_A_REPLY.getKey());
		counsellingRoom.setCourTimeStart(new Date());
		counsellingRoom.setCreateTime(new Date());
		return counsellingRoom;
	}

	/**
	 * 获取云信账户
	 *
	 * @param userId
	 * @return
	 */
	public YunxinUserEntity getYunXinUser(Long userId) {
		YunxinUserEntity yunxinUserModel = new YunxinUserEntity();
		yunxinUserModel.setUserId(userId);
		List<YunxinUserEntity> yunxinUsers = yunxinUserDao.select(yunxinUserModel);
		if (yunxinUsers != null && yunxinUsers.size() != 0) {
			return yunxinUsers.get(0);
		}
		return new YunxinUserEntity();
	}


	public List<StudioPersonnelEntity> getStudioPersonnel(Long stodioId, Long doctorId) {
		return studioPersonnelSV.selectList(StudioPersonnelEntity.builder().dsId(stodioId).doctId(doctorId).build());
	}

	/**
	 * 状态判断
	 *
	 * @param returnParams
	 * @return
	 */
	private Boolean boo(List<HuaweiReturnVo> returnParams) {
		if (returnParams.size() == 0) {
			return true;
		}
		int zero = 0;
		int one = 0;
		for (HuaweiReturnVo param : returnParams) {
			if (param.getRecordFlag() == 0) {
				zero++;
			} else if (param.getRecordFlag() == 1) {
				one++;
			}
		}
		if (zero != 0 && one / zero == 0) {
			return true;
		}
		return false;
		//return returnParams.stream().filter(n->n.getRecordFlag()== 0 || n.getRecordFlag() == 1).count()>0 ? true : false;
	}

	/**
	 * d电话订单回显(评价/答谢/)
	 *
	 * @param currId
	 * @param userType
	 * @param ioId
	 * @param orderVo
	 */
	private void phoneOtherDtail(Long currId, String userType, Long ioId, OrderAndFileVO orderVo) {
		//患者端调用数据返回
		if (UserUserTypeEnum.PATIENT.getKey().equals(userType)) {
			//评价记录
			PhoneOrderCommentRecord record = iCommentRecordSV.selectComment(currId, ioId);
			orderVo.setCommentRecord(record);
			//查询当前患者对该订单答谢记录
			MindVo mind = mindSV.selectMind(currId, ioId);
			orderVo.setMind(mind);

		}

	}

	/**
	 * 医生电话订单回显
	 *
	 * @param currId
	 * @param userType
	 * @param ioId
	 * @return
	 */
	@Override
	public List<OrderAndFileVO> selectOrderEcho(Long currId, String userType, Long ioId) {
		List<OrderAndFileVO> order = mapper.selectOrderEcho(ioId);
		OrderAndFileVO orderVo = order.get(0);
		phoneOtherDtail(currId, userType, ioId, orderVo);


//		if (null == record) {
//			orderVo.setEvaluationFlag(false);
//		} else {
//			orderVo.setEvaluationFlag(true);
//		}
		Date time = orderVo.getAppointTime();
		Date date = new Date();
		int duration = orderVo.getPrDuration();
		CounsellingRoomEntity room = counsellingRoomSV.selectOne(CounsellingRoomEntity.builder().ioId(ioId).build());
		String state = room.getCourState();
		if (time.getTime() > date.getTime()) {
			//第一个是刚下单(未拨打且未超时)  预约时间大于当前时间
			orderVo.setDialStatus("01");
		} else if (time.getTime() + TimeUnit.MINUTES.toMillis(duration) < date.getTime() && orderVo.getReturnParams().size() == 0) {
			//第二是超时未拨打(没打过一次)
			orderVo.setDialStatus("02");
		} else if (CounsellingRoomStateEnum.HAVE_A_REPLY.getKey().equals(state)) {
			//第四订单正常结束(电话未结束通话中或者未到时间问题解决)

			orderVo.setDialStatus("04");
		} else if (CounsellingRoomStateEnum.HAS_ENDED.getKey().equals(state)
				|| CounsellingRoomStateEnum.HAVE_SUMMARIZED.getKey().equals(state)) {
			//已经结束
			orderVo.setDialStatus("05");
		} else if (boo(orderVo.getReturnParams())) {
			//第三是超时时间内拨打未接通(此时订单已超时)
			orderVo.setDialStatus("03");
		}
		if (time.getTime() < date.getTime() && date.getTime() < time.getTime() + TimeUnit.MINUTES.toMillis(duration)) {
			orderVo.setFlag(true);
		} else {
			orderVo.setFlag(false);
		}
		//录音文件
		List<RecordAndTimeVo> result = orderVo.getRecordUrl();
		String fileId = null;
		String[] fileIds = null;
		List<RecordAndTimeVo> list = new ArrayList<>();
		if (!result.isEmpty()) {
			if (result.get(0).getFileInfoId() != null && !"".equals(result.get(0).getFileInfoId())) {
				fileId = result.get(0).getFileInfoId();
				if (!fileId.contains(",")) {
					orderVo.setRecordUrl(result);
				} else {
					fileIds = fileId.split(",");
					for (int i = 0; i < fileIds.length; i++) {
						result.get(i).setFileInfoId(fileIds[i]);
						list.add(result.get(i));
					}
					orderVo.setRecordUrl(list);
				}
			}
		}
		return order;
	}

	/***
	 * 不支付取消电话订单释放当前时间
	 * @param ioId
	 */
	private void freedTime(Long ioId) {
		SimpleDateFormat hourFormat = new SimpleDateFormat("HH:mm:ss");
		SimpleDateFormat weekFormat = new SimpleDateFormat("EEEE", Locale.CHINESE);
		InquiryOrderEntity order = this.selectById(ioId);
		OrderFlowRecordEntity newByOrderId = orderFlowRecordSV.findNewByOrderId(ioId);
		if (newByOrderId != null) {
			Date time = order.getAppointTime();
			String hour = hourFormat.format(time);
			String week = weekFormat.format(time);
			DoctorServiceItemEntity doctorServiceItems = doctorServiceItemSV.selectOne(
					DoctorServiceItemEntity.builder()
							.doctId(newByOrderId.getDoctorId())
							.isOpen(FlagEnum.IS.getKey())
							.seriLabel(DoctorServiceItemEnum.CALL_PHYSICIAN_VISITS.getKey())
							.build()
			);
			doctorPhoneSettingDao.freedTime(doctorServiceItems.getId(), week, hour);
		}
	}


	@Override
	public void fallOrder(String orderId, RedisKeyEnum poolType, UserEntity currentUser) {
		if (poolType == RedisKeyEnum.GENERAL_DOCTOR_POOL) {
			//全科
			if (!orderPoolSV.has(poolType, orderId)) {
				releasePoolOrder(poolType, orderId, currentUser.getId());
				orderPoolSV.put(poolType, orderId);
			}
		} else if (poolType == RedisKeyEnum.SPECIALIST_DOCTOR_POOL) {
			// 专科
			String sql = "select doctor_ds_id  from order_flow_record_view where order_id =  " + orderId;
			Long workId = commonSV.queryField(sql, null, Long.class);
			if (!orderPoolSV.has(poolType, orderId, "WORK", workId.toString())) {
				releasePoolOrder(poolType, orderId, currentUser.getId(), "WORK", workId.toString());
				orderPoolSV.put(poolType, orderId, "WORK", workId.toString());
			}
		}
	}

	@Override
	public void withdrawalOrder(Long orderId) {
		//1.将订单状态更改为退诊
		InquiryOrderEntity inquiryOrder = new InquiryOrderEntity();
		inquiryOrder.setId(orderId);
		inquiryOrder.setIoState(InquiryOrderStateEnum.UNSUBSCRIBE.getKey());
		this.updateById(inquiryOrder);
		// 2.将流转改为作废
		OrderFlowRecordEntity orderFlowRecord = new OrderFlowRecordEntity();
		orderFlowRecord.setOrderId(orderId);
		orderFlowRecord.setStatus(OrderFlowRecordSatusEnum.HAVE_BEEN_ABANDONED.getKey());
		orderFlowRecordSV.updateNewByOrderId(orderFlowRecord);
		// 3.如果是聊天室，更改聊天室状态
		List<CounsellingRoomEntity> counsellingRooms = counsellingRoomDao.select(CounsellingRoomEntity.builder().ioId(orderId).build());
		if (!counsellingRooms.isEmpty()) {
			CounsellingRoomEntity counsellingRoom = counsellingRooms.get(0);
			counsellingRoom.setCourState(CounsellingRoomStateEnum.HAS_ENDED.getKey());
			counsellingRoomDao.updateByPrimaryKeySelective(counsellingRoom);
		}
	}

	@Override
	public List<ResultDoctor> recommendOtherDoctors(Long orderId) {
		List<ResultDoctor> result = new ArrayList<>();
		// 推荐相同科室的医生.查看流转，有工作室返回工作室医生ID，没有就医生ID
		OrderFlowRecordEntity newByOrderId = orderFlowRecordSV.findNewByOrderId(orderId);
		Long doctorId = newByOrderId.getDoctorId();
		Long doctorDsId = newByOrderId.getDoctorDsId();
		if (doctorDsId != null) {
			DoctorStudioEntity doctorStudio = doctorStudioSV.selectById(doctorDsId);
			doctorId = doctorStudio.getBelongPerson();
		}
		List<DoctorDetailAllInfoVo> doctorDetailAllInfoVos = doctorDetailsSV.listDoctorAllInfo(DoctorDetailsParam.builder().id(doctorId).build());
		if (!doctorDetailAllInfoVos.isEmpty()) {
			// 获取患者问的科室编码，
			DoctorDetailAllInfoVo doctorDetailAllInfoVo = doctorDetailAllInfoVos.get(0);
			String deptCode = doctorDetailAllInfoVo.getDeptCode();
			DoctorSearchParam query = new DoctorSearchParam();
			query.setCurrUserId(doctorId);
			query.setDoctCategory(CounsellingRoomCourTypeEnum.SPECIALIZED_SUBJECT.getKey());
			Long totalSize = doctorDetailsSV.listStudioMembersCount(query);
			long pageSize = 1;
			long totalPageNum = (totalSize + pageSize - 1) / pageSize;
			long pageNum = RandomUtils.nextLong(1, totalPageNum + 1);
			long limit = (pageNum - 1) * pageSize;
			query.setPageInfo(" limit  " + limit + " , " + pageSize);
			result = doctorDetailsSV.listStudioMembers(query);
		}
		return result;
	}

	@Override
	@Locker(key = RedisKeyEnum.POOL_ORDER_LOCK, paramExp = "0", noGetMsg = "老铁来晚了!")
	public GrabAndAnswerVo grabOrderAnswer(String orderId, RedisKeyEnum poolType, UserEntity currentUser) {
		Long workId = orderExist(poolType, orderId);
		return doctorGrabOrderAnswer(poolType, orderId, currentUser);
	}

	/**
	 * 构造接单并答复聊天室的参数
	 *
	 * @param orderId
	 * @return
	 */
	private GrabAndAnswerVo constructChatRoomParameters(String orderId) {
		String sql = "SELECT  " +
				"a.id,  " +
				"c.id roomMainId,  " +
				"a.patient_id patientId,  " +
				"e.accid patientAccid,  " +
				"e.token patientPwd,  " +
				"d.relation,  " +
				"a.illness_desc content,  " +
				"f.file_infor_id attach,  " +
				"h.head_url patientHead,  " +
				"d.sex patientSex,  " +
				"d.name patientName,  " +
				"g.tr_round chatMaxNum,  " +
				"TIMESTAMPDIFF(YEAR,d.birthday,date_format(now(), '%Y-%m-%d')) patientAge,  " +
				"IFNULL(j.head_url,i.head_url) doctorHead, " +
				"IFNULL(j.id,i.id) doctorId, " +
				"IFNULL(j.real_name,i.real_name) doctorName, " +
				"IFNULL(j.dept_name,i.dept_name) doctorType, " +
				"IFNULL(j.doct_category,i.doct_category) doctCategory, " +
				"IFNULL(j.hos_name,i.hos_name) hosName, " +
				"IFNULL(j.hos_level,i.hos_level) hosLevel " +
				"from inquiry_order a  " +
				"INNER JOIN order_flow_record_view b on a.id = b.order_id  " +
				"INNER join counselling_room c on c.order_flow_record_id = b.id  " +
				"INNER JOIN patient_detail d on d.id = a.patient_id  " +
				"INNER JOIN yunxin_user e on e.user_id = a.user_id  " +
				"INNER JOIN user h on h.id = a.user_id  " +
				"LEFT JOIN inquiry_annex f on f.io_id = a.id  " +
				"LEFT JOIN doctor_service_price ee on ee.id = a.rule_id " +
				"LEFT JOIN text_rule g on ee.rule_id = g.id  " +
				"LEFT JOIN doctor_studio k on k.id = b.doctor_ds_id  " +
				"LEFT JOIN user_doctor_view j on j.id = k.belong_person  " +
				"LEFT JOIN user_doctor_view i on i.id = b.doctor_id  " +
				"where a.id = #{params.id} ";
		Map<String, Object> params = new HashMap<>();
		params.put("id", orderId);
		return commonSV.queryEntity(sql, params, GrabAndAnswerVo.class);
	}

	@Override
	public Integer unPayNum(Long id) {

		return mapper.unPayNum(id);
	}

	@Override
	public List<MyOrderListVo> listMyOrdersPatient(Long userId, Long status) {
		return mapper.listMyOrdersPatient(userId, status);
	}

	@Override
	public MyOrderInfoVo infoMyOrdersPatient(Long orderId) {
		MyOrderInfoVo myOrderInfoVo = mapper.infoMyOrdersPatient(orderId);
		//查询该订单所对应的评价标签
		myOrderInfoVo.setUserTaglibraryModels(userTaglibrarySV.selectModelByIoId(orderId));
		//查询订单的心意记录
		myOrderInfoVo.setMindModel(mindSV.selectByOrderId(orderId));
		return myOrderInfoVo;
	}

	/**
	 * 医生打电话前5分钟发送消息  注意接听电话通知
	 *
	 * @return
	 */
	@Override
	public List<InquiryOrderVo> beforeFiveMinutesOrder() {
		return mapper.beforeFiveMinutesOrder();
	}

	@Override
	public List<OrdersVo> orderReport(String orderDate, String doctorType, String orderType, Long doctorId) {
		Map<String, Date> stringDateMap = constructionDate(orderDate);
		List<OrdersVo> list = mapper.orderReport(stringDateMap.get("first"), stringDateMap.get("last"), doctorType, orderType, doctorId);
		return list;
	}

	/**
	 * 构建开始和结束日期
	 *
	 * @param orderDate
	 */
	private static Map<String, Date> constructionDate(String orderDate) {
		Map<String, Date> map = new HashMap<>();
		//获取传入的日期
		Date date = DateUtil.parseDate(orderDate);
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		Date firstDayOfMonth = DateUtil.beginOfMonth(buildDate(year, month));
		Date lastDayOfMonth = DateUtil.endOfMonth(buildDate(year, month));
		map.put("first", firstDayOfMonth);
		map.put("last", lastDayOfMonth);
		return map;
	}

	/**
	 * 构建日期
	 *
	 * @param year
	 * @param month
	 * @return
	 */
	private static Date buildDate(int year, int month) {
		Calendar instance = Calendar.getInstance();
		instance.set(Calendar.MONTH, month - 1);
		instance.set(Calendar.YEAR, year);
		return instance.getTime();
	}

	@Override
	public MyOrderInfoVo orderReportInfo(Long orderId, DoctorStudioEntity dsId) {
		MyOrderInfoVo myOrderInfoVo = this.infoMyOrdersPatient(orderId);
		OrderFlowRecordEntity newByOrderId = orderFlowRecordSV.findNewByOrderId(orderId);
		if (dsId != null && newByOrderId.getDoctorDsId() != null) {
			//如果不是自己的工作室，获取自己在这个工作室的分成比例，并设置
			if (!newByOrderId.getDoctorDsId().equals(dsId.getId())) {
				StudioPersonnelEntity studioPersonnels = studioPersonnelSV.selectOne(
						StudioPersonnelEntity.builder()
								.dsId(newByOrderId.getDoctorDsId())
								.doctId(newByOrderId.getDoctorId())
								.deleted(FlagEnum.NO.getKey())
								.build()
				);
				List<StudioPersonServiceEntity> studioPersonServices = studioPersonServiceSV.selectList(StudioPersonServiceEntity.builder().build().builder()
						.studioPersonId(studioPersonnels.getId()).build());
				myOrderInfoVo.setStudioPersonServices(studioPersonServices);
			}
		}
		return myOrderInfoVo;
	}

	@Override
	public Double orderReportCountAmount(String orderDate, String doctorType, String orderType, Long doctorId) {
		Map<String, Date> stringDateMap = constructionDate(orderDate);
		return mapper.orderReportCountAmount(stringDateMap.get("first"), stringDateMap.get("last"), doctorType, orderType, doctorId);
	}

	@Override
	public void unPayCancelOrder(Long orderId, OrderFlowRecordSatusEnum orderFlowRecordSatusEnum, InquiryOrderStateEnum orderStateEnum) {
		InquiryOrderEntity order = this.selectById(orderId);
		if (order == null || !order.getPaymentState().equals(InquiryOrderPaymentStateEnum.TO_BE_PAID.getKey())) {
			return;
		}
		String ioNum = order.getIoNum();
		//1.查询微信订单是否支付成功 订单支付方式 (微信支付)
		if (!StringUtils.isEmpty(order.getPaymentWay()) && PaymentWayEnum.WECHAT.getKey().equals(order.getPaymentWay())) {
			//查询微信支付订单并更新微信支付订单
			WxOrderQueryRespData respData = orderPaySV.orderPayQuery(ioNum, DictEnum.valueOfEnum(ConsumeDetailsTdTypeEnum.class, order.getIoType()));

			if (WxTdStateEnum.SUCCESS.getKey().equals(respData.getTradeState())) {
				try {
					String tradeState = respData.getTradeState();
					String timeEnd = respData.getTimeEnd();
					String otherBillTdNo = respData.getTransactionId();
					order.setPaymentTime(DateUtil.parseDate(timeEnd));
					orderPaySV.updateOrderInfo(order, otherBillTdNo);
				} catch (Exception e) {
					log.info("更新微信支付订单异常", e.getCause());
				}
				log.info("更新微信支付订单成功 订单号:{}", ioNum);
				return;
			}
		}

		// 2.订单更改为已取消
		InquiryOrderEntity inquiryOrder = new InquiryOrderEntity();
		inquiryOrder.setId(orderId);
		inquiryOrder.setIoState(orderStateEnum.getKey());
		this.updateById(inquiryOrder);
		inquiryOrder = this.findByModel(InquiryOrderParam.builder().id(orderId).build());
		OrderFlowRecordEntity orderFlowRecord = new OrderFlowRecordEntity();
		orderFlowRecord.setOrderId(orderId);
		orderFlowRecord.setStatus(orderFlowRecordSatusEnum.getKey());
		orderFlowRecordSV.updateNewByOrderId(orderFlowRecord);
		// 3.电话问诊需要释放预约时间
		if (order.getIoType().equals(InquiryOrderIoTypeEnum.TELEPHONE_COUNSELING.getKey())) {
			this.freedTime(orderId);
		}
		//4.优惠券使用状态改为未使用
		if (order.getRelId() != null) {
			CouponReceiveRecordEntity receiveRecord = receiveRecordSV.selectById(order.getRelId());
			//更改领取记录未使用
			receiveRecord.setUserState(CouponUseStateEnum.DONT_USE.getKey());
			receiveRecordSV.updateById(receiveRecord);
		}
		//5. 如果是义诊服务 义诊次数退回给医生
		log.info("订单的定价主键", inquiryOrder.getRuleId());
		if (inquiryOrder.getRuleId() != null) {
			DoctorServicePriceEntity doctorServicePrice = doctorServicePriceSV.selectById(inquiryOrder.getRuleId());
			TextRuleEntity textRule = textRuleSV.selectById(doctorServicePrice.getRuleId());
			if (RuleTypeEnum.YIZHEN_RULES.getKey().equals(textRule.getTrType())) {
				log.info("义诊次数退回给医生");
				textRule.setLastManTime(textRule.getLastManTime() + 1);
				textRuleSV.updateById(textRule);
			}
		}
	}

	/**
	 * 全科医生抢单并答复
	 *
	 * @param orderId
	 * @param user
	 */
	private GrabAndAnswerVo doctorGrabOrderAnswer(RedisKeyEnum poolType, String orderId, UserEntity user) {
		CounsellingRoomCourTypeEnum courType;
		if (poolType == RedisKeyEnum.SPECIALIST_DOCTOR_POOL) {
			courType = CounsellingRoomCourTypeEnum.SPECIALIZED_SUBJECT;
		} else {
			courType = CounsellingRoomCourTypeEnum.GENERAL;
		}
		Long orderIdL = Long.valueOf(orderId);
		// 1.将订单更改为已接单
		InquiryOrderEntity inquiryOrder = new InquiryOrderEntity();
		inquiryOrder.setId(orderIdL);
		inquiryOrder.setIoState(InquiryOrderStateEnum.HAVE_ORDER.getKey());
		this.updateById(inquiryOrder);
		// 2.插入订单流转记录表
		OrderFlowRecordEntity orderFlowRecord = new OrderFlowRecordEntity();
		orderFlowRecord.setOrderId(orderIdL);
		orderFlowRecord.setDoctorId(user.getId());
		orderFlowRecord.setType(courType.getKey());
		orderFlowRecord.setStatus(OrderFlowRecordSatusEnum.HAS_SEIZED_THE_SINGLE.getKey());
		orderFlowRecord.setDoctorOrderTime(new Date());
		if (poolType == RedisKeyEnum.SPECIALIST_DOCTOR_POOL) {
			OrderFlowRecordEntity oldFlow = orderFlowRecordSV.findNewByOrderId(orderIdL);
			orderFlowRecord.setDoctorDsId(oldFlow.getDoctorDsId());
			orderFlowRecord.setDsOrderTime(oldFlow.getDsOrderTime());
		} else {
			StudioPersonnelEntity doctorStudioPerson = getDoctorStudioPersonId(user.getId());
			orderFlowRecord.setDoctorDsId(doctorStudioPerson.getDsId());
			orderFlowRecord.setDsOrderTime(new Date());
		}
		orderFlowRecordSV.save(orderFlowRecord);
		// 3.创建聊天室
		inquiryOrder = this.findById(orderIdL);
		// 2.点击答复后创立聊天室
		Long roomId = createRoomWhenAnswer(inquiryOrder, orderFlowRecord, user.getId());
		// 4.执行和答复聊天室无关的业务操作
		asyncAnswerAfter(inquiryOrder, orderFlowRecord, user.getId(), roomId, courType);
		// 5.创建24小时订单完成任务
		JSONObject params = new JSONObject();
		params.put("orderId", orderIdL);
		params.put("roomId", roomId);
		AutoCompleteOrderTask releasePoolOrderTask = new AutoCompleteOrderTask("超时自动完成订单", TimeUnit.HOURS.toMillis(orderCompletionTime()), params);
		messageSenderSV.sendDelayTask(releasePoolOrderTask);
		// 6.检测发送模板扩展消息
		inquiryOrderContentSV.sendExpandMsg2Doctor(inquiryOrder, roomId, user.getId());
		// 构造聊天室必须参数
		GrabAndAnswerVo grabAndAnswerVo = constructChatRoomParameters(orderId);
		// end,从抢单池移除该订单
		if (poolType == RedisKeyEnum.SPECIALIST_DOCTOR_POOL) {
			orderPoolSV.remove(poolType, orderId, "WORK", orderFlowRecord.getDoctorDsId().toString());
		} else {
			orderPoolSV.remove(poolType, orderId);
		}
		return grabAndAnswerVo;
	}


	/**
	 * 答复订单创建聊天室,
	 * 构建一条咨询室记录,构建工作室前,先查询是否已经有聊天室.有不创建
	 *
	 * @param inquiryOrder
	 * @param orderFlowRecord
	 * @param currentDocId
	 * @return
	 */
	private Long createRoomWhenAnswer(InquiryOrderEntity inquiryOrder, OrderFlowRecordEntity orderFlowRecord, Long currentDocId) {
		Long roomId = -1L;
		// 工作室人员ID获取
		List<StudioPersonnelEntity> studioInfo = getStudioPersonnel(orderFlowRecord.getDoctorDsId(), currentDocId);
		Long studioPersonId = !studioInfo.isEmpty() ? studioInfo.get(0).getId() : null;
		List<CounsellingRoomEntity> count = counsellingRoomDao.select(CounsellingRoomEntity.builder().ioId(inquiryOrder.getId()).dsId(studioPersonId).build());
		if (count.isEmpty()) {
			CounsellingRoomEntity counsellingRoom = geneCounsellingRoom(inquiryOrder.getId(), inquiryOrder.getUserId(), orderFlowRecord.getId(), currentDocId, studioPersonId);
			// 聊天室创建
			counsellingRoomDao.insertSelective(counsellingRoom);
			// 添加双方到聊天室人员
			ChatroomPersonnelEntity chatroomPersonnel = new ChatroomPersonnelEntity();
			chatroomPersonnel.setCourId(counsellingRoom.getId());
			chatroomPersonnel.setPersonType(UserUserTypeEnum.PATIENT.getKey());
			chatroomPersonnel.setCrpUserid(inquiryOrder.getUserId());
			chatroomPersonnel.setCreateTime(new Date());
			chatroomPersonnelSV.insert(chatroomPersonnel);
			chatroomPersonnel.setCrpUserid(orderFlowRecord.getDoctorId());
			chatroomPersonnel.setPersonType(UserUserTypeEnum.DOCTOR.getKey());
			chatroomPersonnelSV.insert(chatroomPersonnel);
			roomId = counsellingRoom.getId();
		} else {
			roomId = count.get(0).getId();
		}
		return roomId;
	}

	/**
	 * @param inquiryOrder    订单详情
	 * @param orderFlowRecord 流转详情
	 * @param currentDocId    当前医生ID
	 * @param doctorType      当前医生类型
	 */
	private void asyncAnswerAfter(InquiryOrderEntity inquiryOrder, OrderFlowRecordEntity orderFlowRecord, Long currentDocId, Long roomId, CounsellingRoomCourTypeEnum doctorType) {
		log.info("异步方法，答复后，需要做的后续操作 订单号: {}", inquiryOrder.getIoNum());
		// 异步和主业务无关业务
		GlobalThreadPool.execute(() -> {
			Long doctorId = orderFlowRecord.getDoctorId();
			if (orderFlowRecord.getDoctorDsId() != null) {
				//如果抢单人的工作室ID不为空，则医患关系建立为宿主和患者
				DoctorStudioEntity doctorStudio = doctorStudioSV.selectById(orderFlowRecord.getDoctorDsId());
				doctorId = doctorStudio.getBelongPerson();
			}
			// 建立医患关系
			establishDoctorPatientRelationship(inquiryOrder.getPatientId(), doctorId);

			//构建接单答复消息并发送
			informationSV.generateInquiryInformation(inquiryOrder.getId(), Constants.InquiryAdvice.ANSWER);
			// 发送接单答复的短信通知
			UserEntity patientUser = userSV.selectById(inquiryOrder.getUserId());
			UserEntity doctor = userSV.selectById(doctorId);
			String servicePhone = configSV.getValueByKey(Constants.SysConfigKey.SERVICE_PHONE);
			SmsUtil.sendSms(patientUser.getPhoneNo(), SmsTemplateEnum.DOCTOR_FIRST_REPLY, doctor.getRealName(), String.valueOf(orderCompletionTime()), servicePhone);
		});
	}

	/**
	 * 订单完成时间获取
	 *
	 * @return
	 */
	private long orderCompletionTime() {
		Long orderCompletionTime = 1L;
		String servicePhone = configSV.getValueByKey(Constants.SysConfigKey.ORDER_COMPLETION_TIME);
		if (StringUtil.isNotBlank(servicePhone)) {
			return Long.valueOf(servicePhone);
		}
		return orderCompletionTime;
	}

	/**
	 * 订单过期时间获取
	 *
	 * @return
	 */
	private long orderExpirationTime() {
		Long orderExpirationTime = 5L;
		String servicePhone = configSV.getValueByKey(Constants.SysConfigKey.ORDER_EXPIRATION_TIME);
		if (StringUtil.isNotBlank(servicePhone)) {
			return Long.valueOf(servicePhone);

		}
		return orderExpirationTime;
	}

	/**
	 * 验证订单是否可以答复
	 *
	 * @param orderId
	 * @param doctId
	 * @return
	 */
	private OrderFlowRecordEntity verifyCanReply(Long orderId, Long doctId) {
		OrderFlowRecordEntity orderFlowRecord = orderFlowRecordSV.findNewByOrderId(orderId);
		if (orderFlowRecord == null || !orderFlowRecord.getDoctorId().equals(doctId)) {
			throw new BusinessException("该订单超时未答复,订单已释放!");
		}
		if (orderFlowRecord.getStatus().equals(OrderFlowRecordSatusEnum.HAVE_BEEN_ABANDONED.getKey())) {
			throw new BusinessException("该订单超时未答复,订单已释放!");
		}
		return orderFlowRecord;
	}

	/**
	 * 获取医生的工作室人员ID
	 *
	 * @param doctId
	 * @return
	 */
	private StudioPersonnelEntity getDoctorStudioPersonId(Long doctId) {
		List<StudioPersonnelEntity> studioPersonnel = studioPersonnelSV.selectList(StudioPersonnelEntity.builder().build().builder()
				.doctId(doctId)
				.deleted(FlagEnum.NO.getKey())
				.build());
		if (studioPersonnel == null || studioPersonnel.isEmpty()) {
			throw new BusinessException("该医生没有工作室");
		}
		return studioPersonnel.get(0);
	}

	/**
	 * 判定订单池是否有该订单,存在返回专科医生的工作室ID
	 *
	 * @param poolType
	 * @param orderId
	 */
	private Long orderExist(RedisKeyEnum poolType, String orderId) {
		if (poolType == RedisKeyEnum.GENERAL_DOCTOR_POOL) {
			// 判定池中是否有该订单
			boolean has = orderPoolSV.has(poolType, orderId);
			if (!has) {
				throw new BusinessException("订单已被抢！");
			}
			return -1L;
		} else {
			// 判定池中是否有该订单
			String sql = "select doctor_ds_id  from order_flow_record_view where order_id =  " + orderId;
			Long workId = commonSV.queryField(sql, null, Long.class);
			boolean has = orderPoolSV.has(poolType, orderId.toString(), "WORK", workId.toString());
			if (!has) {
				throw new BusinessException("订单已被抢！");
			}
			return workId;
		}
	}

	@Override
	public void orderRevision(Long orderId, String attach, String content) {
		InquiryOrderEntity inquiryOrder = this.selectById(orderId);
		if (inquiryOrder == null) {
			throw new BusinessException("订单异常！");
		}
		//重新设置订单内容及附件
		InquiryOrderEntity updateOrder = new InquiryOrderEntity();
		updateOrder.setId(orderId);
		updateOrder.setIllnessDesc(content);
		updateOrder.setIoState(InquiryOrderStateEnum.WAITING_LIST.getKey());
		updateOrder.setCreateTime(new Date());
		this.updateById(updateOrder);
		OrderFlowRecordEntity orderFlowRecord = orderFlowRecordSV.findNewByOrderId(orderId);
		if (orderFlowRecord != null) {
			OrderFlowRecordEntity newRecord = new OrderFlowRecordEntity();
			BeanUtils.copyProperties(orderFlowRecord, newRecord);
			newRecord.setStatus(OrderFlowRecordSatusEnum.NOT_ROB_SINGLE.getKey());
			newRecord.setDsOrderTime(new Date());
			orderFlowRecordSV.insert(newRecord);
		}
		if (StringUtils.isNotBlank(attach)) {
			int countAttach = inquiryAnnexSV.countByParams(InquiryAnnexEntity.builder().ioId(orderId).build());
			InquiryAnnexEntity inquiryAnnexes = new InquiryAnnexEntity();
			inquiryAnnexes.setFileInforId(attach);
			if (countAttach > 0) {
				inquiryAnnexSV.updateByParams(inquiryAnnexes, TK.selectWhere(InquiryAnnexEntity.class).andEqualTo(InquiryAnnexEntity::getIoId, orderId).end());
			} else {
				inquiryAnnexes.setIoId(orderId);
				inquiryAnnexes.setIoNum(inquiryOrder.getIoNum());
				inquiryAnnexSV.insert(inquiryAnnexes);
			}
		}

		// 放入订单池，如果是图文问诊，且不是继续咨询，才需要放入订单池
		if (
				InquiryOrderIoTypeEnum.BY_CONSULTING.getKey().equals(inquiryOrder.getIoType())
						&& !InquiryOrderSourceEnum.CONTINUE_CONSULT.getKey().equals(inquiryOrder.getOrderSource())
		) {
			if (orderFlowRecord == null || OrderFlowRecordTypeEnum.GENERAL.getKey().equals(orderFlowRecord.getType())) {
				orderPoolSV.put(RedisKeyEnum.GENERAL_DOCTOR_POOL, orderId.toString());
			} else if (OrderFlowRecordTypeEnum.SPECIALIZED_SUBJECT.getKey().equals(orderFlowRecord.getType())) {
				orderPoolSV.put(RedisKeyEnum.SPECIALIST_DOCTOR_POOL, orderId.toString(), "WORK", orderFlowRecord.getDoctorDsId().toString());
			}
		}
		// 重新推送
		jpushAccountSV.pushOrderMsg2Doctors(orderId);
	}

	@Override
	public InquiryOrderEntity selectByIoNum(String ioNum) {
		List<InquiryOrderEntity> inquiryOrders = this.selectList(InquiryOrderEntity.builder().ioNum(ioNum).build());
		return (inquiryOrders.isEmpty()) ? null : inquiryOrders.get(0);
	}

	/**
	 * 电话问诊当天总量
	 *
	 * @param patientId
	 * @param time
	 * @return
	 */
	@Override
	public int selectCountPh(Long patientId, Date time) {
		return mapper.selectCountPh(patientId, time);
	}

	@Override
	public long getMinutesReserved(Long appointTimeRule, Date appointTime, InquiryOrderIoTypeEnum videoConsultation) {
		return mapper.getMinutesReserved(appointTimeRule, appointTime, videoConsultation.getKey());
	}

	/**
	 * 患者下单限制
	 * (相同医生同一患者不可重复下单)
	 *
	 * @param patientId
	 * @param doctId
	 * @return
	 */
	@Override
	public OrderVo samePatientLimit(long patientId, long doctId) {
		return mapper.samePatientLimit(patientId, doctId);
	}

	/**
	 * 图文重复订单判断
	 *
	 * @param dsId
	 * @return
	 */
	@Override
	public List<OrderVo> selectRepeatOrder(Long dsId, Long doctId, Long userId, Long patientId) {
		return mapper.selectRepeatOrder(dsId, doctId, userId, patientId);
	}

	@Override
	public long getPatientAskNum(Long doctId, Long patientId) {
		final long patientAskNum = mapper.getPatientAskNum(doctId, patientId);
		return patientAskNum;
	}

	/**
	 * 查询患者义诊医生 (最多三次)
	 *
	 * @param userId 患者主键
	 * @return
	 */
	@Override
	public List<Long> queryClinicTime(Long userId) {
		//查询患者本周内的义诊医生
		List<Long> clinicDoctors = mapper.queryClinicTime(userId);
		return (clinicDoctors.isEmpty()) ? null : clinicDoctors;
	}

	@Override
	public boolean updateInquiryOrder(OrderAndFileParam inquiryOrder) {
		List<InquiryOrderEntity> inquiryOrders = this.selectList(InquiryOrderEntity.builder().ioNum(inquiryOrder.getIoNum()).build());
		if (inquiryOrders.isEmpty()) {
			throw new BusinessException("该订单不存在!");
		}
		this.updateByParams(inquiryOrder.covert(), TK.selectWhere(InquiryOrderEntity.class).andEqualTo(InquiryOrderEntity::getIoNum, inquiryOrder.getIoNum()).end());

		/*保存附件信息*/
		if (inquiryOrder.getIds() != null) {
			if (inquiryOrder.getIds().split(",").length > 0) {
				String[] split = inquiryOrder.getIds().split(",");
				for (String id : split) {
					String ioNum = inquiryOrder.getIoNum();
					InquiryAnnexEntity inquiryAnnex = new InquiryAnnexEntity();
					inquiryAnnex.setIoNum(ioNum);
					inquiryAnnex.setFileInforId(id);
					inquiryAnnexDao.insertSelective(inquiryAnnex);
				}
			}
		}
		return true;
	}

	@Override
	public List<ConsultingOrderVO> consultingOrderList(ConsultingOrderParam query) {
		return this.mapper.consultingOrderList(query);
	}

	@Override
	public ConsultingOrderInfoVO consultingOrderInfo(Long orderId) {
		ConsultingOrderInfoVO consultingOrderInfoVO = this.mapper.consultingOrderInfo(orderId);
		AxbResultEntity model = AxbResultEntity.builder().ioId(orderId).build();
		AxbResultEntity result = iAxbResultSV.selectOne(model);
		String fileId = null;
		String[] fileIds = null;
		List<String> filePaths = new ArrayList<>();
		if (result != null && result.getFileInfoId() != null){
			fileId = result.getFileInfoId();
			if (!fileId.contains(",")){
				filePaths.add(fileId);
				consultingOrderInfoVO.setRecordUrl(filePaths);
			}else {
				fileIds = fileId.split(",");
				for (int i = 0; i < fileIds.length ;i++) {
					filePaths.add(fileIds[i]);
				}
				consultingOrderInfoVO.setRecordUrl(filePaths);
			}
		}
		return consultingOrderInfoVO;
	}

	@Override
	public PageInfo<InquiryTdRecordVO> listInquiryOrderRecord(TdRecordExampleParam tdRecordExampleVO, int pageNo, int limit) {
		PageHelper.startPage(pageNo,limit);
		return new PageInfo<InquiryTdRecordVO>(mapper.listInquiryOrderRecord(tdRecordExampleVO));
	}
}
